//================================================
//  Company     : ICDREC
//  Project     : SG8
//  File name   : tmr3_read_write.v
//  Author      : Nguyễn Việt
//  Date        : August 05th 2014
//  Version     : 
//-------------------------------------------------
// Modification History
// Date: 	By: 
// - 
//=================================================
`include "D:/ICDREC/Design/TIMER 3/RLT_v3/tmr3_define.h"
module tmr3_read_write(
						// clock and reset
						gclk_tmr3,
						reset_n,
						//inputs
						bus_tmr3_sel,
						bus_tmr3_we,
						bus_addr,
						bus_wdata,
						int_tmr_cnt_we,
						int_tmr_cnt_wdata,
						int_cap_cmp_we,
						int_cap_cmp_wdata,
						set_tmrif,
						set_capif,
						set_cmpif,
						sca,
						cnt_en,
						//outputs
						tcon,
						t3cnt,
						cmp,
						tmr3_int,
						tmr3_cap_cmp_int,
						tmr3_on,
						tmr3_rdata,
						t3cnt_en
						);
	// clock and reset
	input 			gclk_tmr3;
	input 			reset_n;
	//inputs
	input	 		bus_tmr3_sel;
	input	 		bus_tmr3_we;
	input 	[3:0] 	bus_addr;
	input 	[7:0]	bus_wdata;
	input 			int_tmr_cnt_we;
	input 			int_tmr_cnt_wdata;
	input 			int_cap_cmp_we;
	input 			int_cap_cmp_wdata;
	input 			set_tmrif;
	input			set_capif;
	input			set_cmpif;
	input			cnt_en;
	//output
	output 			tmr3_int;			
	output 			tmr3_cap_cmp_int;	
	output			cmp;
	output 	[7:0]	tmr3_rdata;
	output 	[5:0]	tcon;
	output 	[5:0]	sca;
	output	[23:0]	t3cnt;
	output			tmr3_on;
	output			t3cnt_en;
	//internal wires and registers
	reg 	[5:0]	tcon;
	reg 	[5:0]	sca;
	reg		[23:0]	t3cnt;
	reg 	[23:0]  cap;
	reg		[23:0]  cmp;
	reg 	[7:0] 	buf_l;
	reg 	[7:0]	buf_h;
	reg 			tmr3_int;
	reg		[7:0]	tmr3_rdata;
	reg 			tmr3_cap_cmp_int;
	reg 			tmr3_on;
	wire			sel_reg_tcon;
	wire 			sel_reg_sca;
	wire 			sel_reg_t3cnt_l;
	wire 			sel_reg_t3cnt_h;
	wire 			sel_reg_t3cnt_u;
	wire 			sel_reg_cmp_l;
	wire 			sel_reg_cmp_h;
	wire 			sel_reg_cmp_u;
	wire 			sel_reg_cap_l;
	wire 			sel_reg_cap_h;
	wire 			sel_reg_cap_u;
	wire 			set_tmrif;
	wire 			set_capif;
	wire 			set_cmpif;
	wire			tcon_en;
	wire			sca_en;
	wire			cmp_en_l;
	wire			cmp_en_h;
	wire			cmp_en_u;	
	wire 			buf_en_l;
	wire			buf_en_h;
	wire			t3cnt_en;
	wire			tmr3_int_en;
	wire			set_ccif;
	wire			tmr3_cap_cmp_int_en;
	wire 			w_buf_l;
	wire 			r_buf_l;
	wire 			w_buf_h;
	wire 			r_buf_h;
	wire			w1;
	wire 			w2;
	wire 			w3;
	wire 			w4;
	wire 			w5;
	wire 			w6;
	wire 			w7;
	wire 			w8;
	wire 			w9;
	wire			w_en;
//decoder
	assign w1 = ~bus_addr[3] & (~bus_addr[2]);
	assign w2 = ~bus_addr[1] & w1;
	assign w3 =  bus_addr[1] & w1;
	assign w4 = ~bus_addr[3] & bus_addr[2];
	assign w5 = ~bus_addr[1] & w4;
	assign w6 =  bus_addr[1] & w4;
	assign w7 =  bus_addr[3] & (~bus_addr[2]);
	assign w8 = ~bus_addr[1] & w7;
	assign w9 =  bus_addr[1] & w7;
	assign sel_reg_tcon	 = ~bus_addr[0] & w2;
	assign sel_reg_sca =   bus_addr[0] & w2;
	assign sel_reg_t3cnt_l = ~bus_addr[0] & w3;
	assign sel_reg_t3cnt_h =  bus_addr[0] & w3;
	assign sel_reg_t3cnt_u = ~bus_addr[0] & w5;
	assign sel_reg_cmp_l =    bus_addr[0] & w5;
	assign sel_reg_cmp_h = ~bus_addr[0] & w6;
	assign sel_reg_cmp_u =  bus_addr[0] & w6;
	assign sel_reg_cap_l = ~bus_addr[0] & w8;
	assign sel_reg_cap_h =  bus_addr[0] & w8;
	assign sel_reg_cap_u = ~bus_addr[0] & w9;
//
//write												
//
	assign w_en = bus_tmr3_sel & bus_tmr3_we;
	assign r_en = bus_tmr3_sel & (~bus_tmr3_we);		

	//register TCON
	assign tcon_en = w_en & sel_reg_tcon;
	always @(posedge gclk_tmr3) begin
		if(reset_n == 1'b0)
			tcon[5:0] <= `DELAY 7'h00;
		else
			if(tcon_en == 1'b1)
				tcon[5:0] <= `DELAY bus_wdata[5:0];
			else
				tcon[5:0] <= `DELAY tcon[5:0];
	end
	always @(posedge gclk_tmr3) begin
		if(reset_n == 1'b0)
			tmr3_on <= `DELAY 1'b0;
		else
			if(tcon_en == 1'b1)
				tmr3_on <= `DELAY bus_wdata[7];
			else
				tmr3_on <= `DELAY tmr3_on;
	end

	//register SCA 
	assign sca_en = w_en & sel_reg_sca;
	always @(posedge gclk_tmr3) begin	
		if(reset_n == 1'b0)
			sca[5:0] <= `DELAY 6'h00;
		else
			if(sca_en == 1'b1)
				sca[5:0] <= `DELAY bus_wdata[5:0];
			else
				sca[5:0] <= `DELAY sca[5:0];
	end
	//register CMP
	assign cmp_en_l = w_en & sel_reg_cmp_l;
	always @(posedge gclk_tmr3) begin
		if(reset_n == 1'b0)
			cmp[7:0] <= `DELAY 8'h00;
		else
			if(cmp_en_l == 1'b1)
				cmp[7:0] <= `DELAY bus_wdata[7:0];
			else
				cmp[7:0] <= `DELAY cmp[7:0];	
	end
	assign cmp_en_h = w_en & sel_reg_cmp_h;
	always @(posedge gclk_tmr3) begin
		if(reset_n == 1'b0)
			cmp[15:8] <= `DELAY 8'h00;
		else
			if(cmp_en_h == 1'b1)
				cmp[15:8] <= `DELAY bus_wdata[7:0];
			else
				cmp[15:8] <= `DELAY cmp[15:8];
	end
	assign cmp_en_u = w_en & sel_reg_cmp_u;
	always @(posedge gclk_tmr3) begin
		if(reset_n == 1'b0)
			cmp[23:16] <= `DELAY 8'h00;
		else
			if(cmp_en_u == 1'b1)
				cmp[23:16] <= `DELAY bus_wdata[7:0];
			else
				cmp[23:16] <= `DELAY cmp[23:16];	
	end
	//register T3CNT
	assign w_buf_l = w_en & sel_reg_t3cnt_h;
	assign r_buf_l = r_en & sel_reg_t3cnt_l;
	assign buf_en_l = sel_reg_t3cnt_h | sel_reg_t3cnt_l;
	always @(posedge gclk_tmr3) begin
		casez({buf_en_l, w_buf_l, r_buf_l})
				3'b11?:	buf_l[7:0] <= `DELAY bus_wdata[7:0];
				3'b101: buf_l[7:0] <= `DELAY t3cnt[15:8]; 
				default: buf_l[7:0] <= `DELAY buf_l[7:0];
		endcase
	end
	
	assign w_buf_h = w_en & sel_reg_t3cnt_u;
	assign r_buf_h = r_en & sel_reg_t3cnt_l;
	assign buf_en_h =  sel_reg_t3cnt_u | sel_reg_t3cnt_l ;
	always @(posedge gclk_tmr3) begin
		casez({buf_en_h, w_buf_h, r_buf_h})
				3'b11?: buf_h[7:0] <= `DELAY bus_wdata[7:0];
				3'b101: buf_h[7:0] <= `DELAY t3cnt[23:16];
				default: buf_h[7:0] <= `DELAY buf_h[7:0];
		endcase
	end

	assign t3cnt_en = w_en & sel_reg_t3cnt_l;
	always @(posedge gclk_tmr3) begin
		if(t3cnt_en == 1'b1)
			t3cnt[23:0] <= `DELAY {buf_h[7:0],buf_l[7:0],bus_wdata[7:0]};
		else
			if(cnt_en)
				t3cnt[23:0] <= `DELAY t3cnt[23:0] + 1'b1;
	end
	//register CAP
	always @(posedge gclk_tmr3) begin
		if(reset_n == 1'b0)
			cap[23:0] <= `DELAY 24'h000000;
		else
			if(set_capif == 1'b1)
				cap[23:0] <= `DELAY t3cnt[23:0];
			else
				cap[23:0] <= `DELAY cap[23:0];
	end
	//set interrupt flat			
	assign tmr3_int_en = set_tmrif | int_tmr_cnt_we;
	always @(posedge gclk_tmr3) begin
		if(reset_n == 1'b0)
			tmr3_int <= `DELAY 1'b0;
		else
			casez({tmr3_int_en, set_tmrif, int_tmr_cnt_we})
					3'b11?: tmr3_int <= `DELAY 1'b1;
					3'b101: tmr3_int <= `DELAY int_tmr_cnt_wdata;
					default: tmr3_int <= `DELAY tmr3_int;
			endcase
	end
	
	assign set_ccif = set_capif | set_cmpif;
	assign tmr3_cap_cmp_int_en = set_ccif | int_cap_cmp_we;
	always @(posedge gclk_tmr3) begin
		if(reset_n == 1'b0)
			tmr3_cap_cmp_int <= `DELAY 1'b0;
		else
			casez({tmr3_cap_cmp_int_en, set_ccif, int_cap_cmp_we})
					3'b11?: tmr3_cap_cmp_int <= `DELAY 1'b1;
					3'b101: tmr3_cap_cmp_int <= `DELAY int_cap_cmp_wdata;
					default: tmr3_cap_cmp_int <= `DELAY tmr3_cap_cmp_int;
			endcase
	end
//
//read													
//
	always @(*)
		begin
			tmr3_rdata[7:0] = 8'h00;
			case(bus_addr)
				4'b0000: tmr3_rdata[6:0] = {tmr3_on,1'b0,tcon[5:0]};
				4'b0001: tmr3_rdata[5:0] = sca[5:0];
				4'b0010: tmr3_rdata[7:0] = t3cnt[7:0];
				4'b0011: tmr3_rdata[7:0] = buf_l;
				4'b0100: tmr3_rdata[7:0] = buf_h;
				4'b0101: tmr3_rdata[7:0] = cmp[7:0];
				4'b0110: tmr3_rdata[7:0] = cmp[15:8];
				4'b0111: tmr3_rdata[7:0] = cmp[23:16];
				4'b1000: tmr3_rdata[7:0] = cap[7:0];
				4'b1001: tmr3_rdata[7:0] = cap[15:8];
				4'b1010: tmr3_rdata[7:0] = cap[23:16];
				default tmr3_rdata[7:0] = 8'h00;
			endcase
		end
endmodule


assign cc_en_l = w_en & sel_reg_cc_l & ~tcon[5];
always @(posedge gclk_tmr3) begin
	if(reset_n == 1'b0)
		cc[7:0] <= `DELAY 8'h00;
	else if(cc_en_l == 1'b1)
			cc[7:0] <= `DELAY bus_wdata[7:0];
		else
			cc[7:0] <= `DELAY cc[7:0];	
end
assign cc_en_h = w_en & sel_reg_cc_h & ~tcon[5];
always @(posedge gclk_tmr3) begin
	if(reset_n == 1'b0)
		cc[15:8] <= `DELAY 8'h00;
	else if(cc_en_h == 1'b1)
			cc[15:8] <= `DELAY bus_wdata[7:0];
		else
			cc[15:8] <= `DELAY cc[15:8];
end
assign cc_en_u = w_en & sel_reg_cc_u & ~tcon[5];
always @(posedge gclk_tmr3) begin
	if(reset_n == 1'b0)
		cc[23:16] <= `DELAY 8'h00;
	else if(cc_en_u == 1'b1)
			cc[23:16] <= `DELAY bus_wdata[7:0];
		else
			cc[23:16] <= `DELAY cc[23:16];	
end


always @(posedge gclk_tmr3) begin
	if(reset_n == 1'b0)
		cc[23:0] <= `DELAY 24'h000000;
	else if(set_capif == 1'b1)
			cc[23:0] <= `DELAY t3cnt[23:0];
		else
			cc[23:0] <= `DELAY cc[23:0];
end




